/**
 * This file contains the application logic. It handles all of the user actions
 * on the page, initializes views, variables and cookies, and makes AJAX
 * requests to the server for the JWTs.
 *
 */

var Xyz = Xyz || {};

(function(app) {
  /**
   * GLOBALS
   */

  /**
   * Shipping cost
   * @type {number}
   */
  app.SHIPPING = 9.99;

  /**
   * Tax cost
   * @type {number}
   */
  app.TAX = 8.00;

  /**
   * Items for sale
   * @type {Xyz.Models.Items}
   */
  app.items;

  /**
   * Currently selected item
   * @type {Xyz.Models.Item}
   */
  app.currentItem;

  /**
   * Shopping cart collection of items
   * @type {Xyz.Models.Cart}
   */
  app.cart;

  /**
   * Buyer information
   * @type {Xyz.Models.User}
   */
  app.user;

  /**
   * VIEWS
   */

  /**
   * Front page view that displays a list of items
   * @type {Xyz.Views.SelectionView}
   */
  var selectorView;

  /**
   * Item details page top half
   * @type {Xyz.Views.CameraInfoView}
   */
  var cameraInfoView;

  /**
   * Item details page bottom half, displays item details and allows the user to
   * add the item to their shopping cart.
   * @type {Xyz.Views.CameraInfoViewBottom}
   */
  var cameraInfoBottomView;

  /**
   * Cart page, displays all items in the cart and implements the continue
   * checkout and Google Wallet buy buttons
   * @type {Xyz.Views.CartView}
   */
  var cartView;

  /**
   * Confirmation page top template
   * @type {Xyz.Views.ConfirmationView}
   */
  var confirmationView;
  /**
   * Confirmation page bottom template
   * @type {Xyz.Views.ConfirmationBottomView}
   */
  var confirmationBottomView;

  /**
   * Receipt page template
   * @type {Xyz.Views.ReceiptView}
   */
  var receiptView;

  /**
   * INIT
   */

  /**
   * Initializes cookies, items, buttons, views, login for application
   */
  function init() {
    // Init items
    app.items = initItems();

    // Init our user and items
    app.user = new Xyz.Models.User();
    app.currentItem = new Xyz.Models.CurrentItem();
    app.cart = new Xyz.Models.Cart();

    // If the DOM is ready append our view elements
    if (document.readyState === 'interactive' ||
            document.readyState === 'complete') {
      initApp();
    }
    // If it's not ready add an event handler to intialize it when ready
    else {
      document.addEventListener('DOMContentLoaded', function() {
        initApp();
      });
    }
  }

  /**
   * Inits the application
   */
  function initApp() {
    // Load Views
    initViews();
    // Load SSO login menu
    loginMenuLoader();
    // Bind actions to all elements that are not generated by a view
    initActions();
    // Init cookies
    initCookies();
    // Init auth
    Xyz.Wallet.checkAuth();
    // Init Wallet if page is being reloaded
    Xyz.Wallet.createButton();
  }

  /**
   * Initializes the backbone template views and binds them with their
   * respective models
   */
  function initViews() {
    // Initiate views
    // The selector view is the front page of the application it displays the
    // items available for sale and enables users to drill down to their
    //selection
    selectorView = new Xyz.Views.SelectionView({
      collection: app.items
    });

    // Renders the details of the current item
    cameraInfoView = new Xyz.Views.CameraInfoView({
      model: app.currentItem
    });
    cameraInfoBottomView = new Xyz.Views.CameraInfoViewBottom({
      model: app.currentItem
    });

    // Renders the current items in the shopping cart
    // Full cart functionality is mocked and only a single item is displayed at
    // a time
    cartView = new Xyz.Views.CartView({
      collection: app.cart
    });

    // Renders the purchase confirmation page. Allows users to edit their Wallet
    // selections
    confirmationView = new Xyz.Views.ConfirmationView({
        collection: app.cart,
        model: app.user
    });
    confirmationBottomView = new Xyz.Views.ConfirmationBottomView({
      collection: app.cart
    });

    // renders the receipt page
    receiptView = new Xyz.Views.ReceiptView({
        collection: app.cart,
        model: app.user
    });
  }

  /**
   * Attaches click handlers to actionable HTML elements not handled by views
   */
  function initActions() {
    $('#add_to_cart').on('click', addToCart);
    $('#continue_shopping').on('click', function() {
      $.mobile.changePage('#item-selection', {
        transition: 'slide'
      });
    });
    $('#receipt_continue_shopping').on('click', function() {
      $.mobile.changePage('#item-selection', {
        transition: 'slide'
      });
    });
    $('#continue_checkout').on('click', Xyz.Wallet.requestMaskedWallet);
    $('#change_shipping').on('click', Xyz.Wallet.changeMaskedWallet);
    $('#change_payment_confirm').on('click', Xyz.Wallet.changeMaskedWallet);
    $('#place_order').on('click', Xyz.Wallet.requestFullWallet);
    $('#login_with_google').on('click', function() {
        Xyz.Sso.login(function() {
          //continue to checkout?
          $.mobile.changePage('#confirmation-page', {
            transition: 'slide'
          });
        });
      });
    $('#change_payment').on('click', function() {
        $.mobile.changePage('#payment-selector-page')});
    $('#native_log_in').on('click', notImplemented);
    $('#forgot_password').on('click', notImplemented);
    $('#create_account').on('click', notImplemented);
  }

  /**
   * Initializes variables from stored cookie information. Information is
   * persisted on via cookies instead of by server session to try and be more
   * server agnostic.
   */
  function initCookies() {
    app.currentItem.setItem(Xyz.Cookie.getCurrentItem());
    app.cart.add(app.currentItem.get('item'));
    app.user.set('maskedWallet', Xyz.Cookie.getMaskedWallet());
  }

  /**
   * Initializes items for sale.
   * @return {array} array of items.
   */
  function initItems() {
    // Define camera information
    var cameras = [];
    cameras[0] = new Xyz.Models.Item({
        id: '0',
        name: 'XY000',
        price: 800,
        desc: '<li id="camera_desc">High Resolution 16.2 MP DX-format CMOS ' +
              'sensor Body only.' +
              '</li><li id="camera_desc">Lenses sold separately High Speed ' +
              '6 frames per second' +
              ' continuous shooting up to 100 shots</li>',
        image: 'img/XY000-small.png'
    });
    cameras[1] = new Xyz.Models.Item({
        id: '1',
        name: 'XY001',
        price: 1950,
        desc: '<li id="camera_desc">High Resolution 16.2 MP DX-format CMOS ' +
              'sensor Body only. </li>' +
              '<li id="camera_desc">Lenses sold separately High Speed 6 ' +
              'frames per second ' +
              'continuous shooting up to 100 shots</li>',
        image: 'img/XY001-small.png'
    });
    cameras[2] = new Xyz.Models.Item({
        id: '2',
        name: 'XY002',
        price: 2100,
        desc: '<li id="camera_desc">High Resolution 16.2 MP DX-format CMOS ' +
              'sensor Body only.</li>' +
              '<li id="camera_desc">Lenses sold separately High Speed 6 ' +
              'frames per second ' +
              'continuous shooting up to 100 shots</li>',
        image: 'img/XY002-small.png'
    });
    items = new Xyz.Models.Items();
    for (var camera in cameras) {
      items.add(cameras[camera]);
    }
    return items;
  }

  /**
   * Initializes the login menu
   */
  function loginMenuLoader() {
    $('#login-button').click(app.login);
    $('body').bind('hideOpenMenus', function() {
      $('ul:jqmData(role=\'menu\')').find('li > ul').hide();
    });

    var menuHandler = function(e) {
      $('body').trigger('hideOpenMenus');
      $(this).find('li > ul').show();
      e.stopPropagation();
    };

    $('ul:jqmData(role=\'menu\') li > ul li').click(function(e) {
      $('body').trigger('hideOpenMenus');
      e.stopPropagation();
    });

    $('body').delegate('ul:jqmData(role=\'menu\')', 'click', menuHandler);
    $('body').click(function(e) {
      $('body').trigger('hideOpenMenus');
    });
  }

  /**
   * Redirects buyers to the Google account sign in page and asks them for
   * authorization
   */
  app.login = function() {
    Xyz.Sso.login();
  };

  /**
   * Clears the session object of buyer's Google account profile in the scope of
   * XYZ sample.
   */
  app.logout = function() {
    Xyz.Sso.logout();
  };

  /**
   * BUY FLOW
   */

  /**
   * This function requests initiates the process of adding a GoogleWalletButton
   */
  function addToCart() {
    // should always generate the JWT again, or the button
    // will be based off old info in the cookie

    // Since the cart is currently mocked we pop the previous item first
    app.cart.pop();
    // Then add the current item so we only have a single item in the cart
    // at a time. In the future, this will be built out to a multi item cart.
    app.cart.add(app.currentItem.get('item'));
    Xyz.Wallet.createButton();
    // Move to next page
    $.mobile.changePage('#order-detail', {
      transition: 'slide'
    });
  }

  /**
   * @param {number} itemId selected item to purchase.
   */
  app.select = function(itemId) {
    var camera = items.get(itemId);
    app.currentItem.setItem(camera);
    $.mobile.changePage('#camera-detail', {
      transition: 'slide'
    });
  };

  /**
   * Function to tie to buttons which are only for demonstration
   */
  function notImplemented() {
    alert('sample button, not implemented');
  }

  /**
   * Fix for IE9 console not existing until F12 dev tools are opened
   */
  if (!window.console) window.console = {};

  /**
   * Fix for IE9 console not existing until F12 dev tools are opened
   */
  if (!window.console.log) window.console.log = function() {};

  /**
   * Fix to ensure JSON.parse works correctly on Android 2.3.7
   * @type {function}
   */
  JSON.tempParse = JSON.parse;

  /**
   * Overwriting JSON.parse for Android 2.3.7 devices.  JSON.parse(null) returns
   * an error instead of null
   *
   * @param {string} text JSON string to parse.
   * @return {object} JS object.
   */
  JSON.parse = function(text) {
    if (text) {
      return JSON.tempParse(text);
    } else {
      return null;
    }
  };
  init();
})(window.Xyz.App = window.Xyz.App || {});

